package com.ticket.sass.provider.util;

import com.ticket.sass.provider.service.BaseService;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author ywb
 * @date 2024-04-02 14:20
 */
public class AutoFetchUtil {
    public static <T, E> void autoFetchOne(List<T> dataList, BaseService<E> service, String relationField, String localKey, String foreignKey) {
        for (T data : dataList) {
            for (Field field : data.getClass().getDeclaredFields()) {
                if (field.getName().equals(relationField)) {
                    field.setAccessible(true);
                    try {
                        Object localKeyValue = getFieldValue(data, localKey);
                        E relationData = service.getBy(localKeyValue, foreignKey);
                        field.set(data, relationData);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    public static <T, E> void autoFetchMany(List<T> dataList, BaseService<E> service, String relationField, String localKey, String foreignKey) {
        List<Object> localKeyValues = dataList.stream()
            .map(data -> getFieldValue(data, localKey))
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
        
        List<E> relationDataList = service.getBy(localKeyValues, foreignKey);
        
        for (T data : dataList) {
            List<E> filteredData = relationDataList.stream()
                .filter(relationData -> Objects.equals(getFieldValue(data, localKey), getFieldValue(relationData, foreignKey)))
                .collect(Collectors.toList());
            
            setFieldValue(data, relationField, filteredData);
        }
    }
    
    private static <T> Object getFieldValue(T object, String fieldName) {
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(object);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static <T, E> void autoFetchOne(T data, BaseService<E> service, String relationField, String localKey, String foreignKey) {
        for (Field field : data.getClass().getDeclaredFields()) {
            if (field.getName().equals(relationField)) {
                field.setAccessible(true);
                try {
                    Object localKeyValue = getFieldValue(data, localKey);
                    E relationData = service.getBy(localKeyValue, foreignKey);
                    field.set(data, relationData);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public static <T, E> void autoFetchMany(T data, BaseService<E> service, String relationField, String localKey, String foreignKey) {
        Object localKeyValue = getFieldValue(data, localKey);
        
        if (localKeyValue != null) {
            List<E> relationDataList = service.getListBy(localKeyValue, foreignKey);
            
            for (Field field : data.getClass().getDeclaredFields()) {
                if (field.getName().equals(relationField)) {
                    field.setAccessible(true);
                    try {
                        field.set(data, relationDataList);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    private static <T> void setFieldValue(T object, String fieldName, Object value) {
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(object, value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}